package org.itzheng.myrxframe.realize.apk;

import android.Manifest;
import android.app.usage.StorageStats;
import android.app.usage.StorageStatsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.support.annotation.Nullable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import org.itzheng.and.activity.permissions.IPermissionManager;
import org.itzheng.and.baseutils.common.ArrayUtils;
import org.itzheng.and.baseutils.log.LogHelper;
import org.itzheng.and.baseutils.ui.UIUtils;
import org.itzheng.myrxframe.R;
import org.itzheng.myrxframe.base.BaseActivity;
import org.itzheng.myrxframe.base.BaseV4Fragment;
import org.itzheng.myrxframe.http.retrofit.utils.FileManager;
import org.itzheng.myrxframe.http.rxjava.RxHelper;
import org.itzheng.myrxframe.realize.adpter.rcv.ApkListAdapter;
import org.itzheng.myrxframe.realize.apk.utils.AppUtils;

import java.io.File;
import java.io.IOException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;

/**
 * Title:<br>
 * Description: <br>
 *
 * @email ItZheng@ZoHo.com
 * Created by itzheng on 2019-4-15.
 */
public class ApkListFragment extends BaseV4Fragment {
    private static final String BUNDLE_ENUM_TYPE = "BUNDLE_ENUM_TYPE";
    private static final String TAG = "ApkListFragment";
    Unbinder unbinder;
    @BindView(R.id.rcvContent)
    RecyclerView rcvContent;
    @BindView(R.id.btnOneKeyBackup)
    Button btnOneKeyBackup;

    public static ApkListFragment newInstance(Type type) {
        Bundle args = new Bundle();
        args.putSerializable(BUNDLE_ENUM_TYPE, type);
        ApkListFragment fragment = new ApkListFragment();
        fragment.setArguments(args);
        return fragment;
    }

    PackageManager mPackageManager;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (rootView == null) {
            rootView = UIUtils.inflate(R.layout.fragment_apk_list);
        }
        unbinder = ButterKnife.bind(this, rootView);
        mPackageManager = getActivity().getPackageManager();
        setModel(currentModel);
        return rootView;
    }

    @Override
    protected void onFirstVisible() {
        super.onFirstVisible();
        initData();
    }

    public String getTitle() {
        Type type = getType();
        switch (type) {
            case ALL:
            default:
                return "全部";
            case SYSTEM:
                return "系统";
            case USER:
                return "用户";

        }

    }

    private Type getType() {
        Bundle args = getArguments();
        Type type = (Type) args.getSerializable(BUNDLE_ENUM_TYPE);
        return type;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        unbinder.unbind();
    }

    /**
     * 添加App
     *
     * @param pkgName
     */
    public void addApp(String pkgName) {
        //直接重新获取
        if (!isFirstVisible) {
            //只要打开过，就可以重新加载
            initData();
        }
    }

    /**
     * 移除app
     *
     * @param pkgName
     */
    public void removeApp(String pkgName) {
        if (!ArrayUtils.isEmpty(mItems)) {
            for (PackageInfo item : mItems) {
                if (item.packageName.equalsIgnoreCase(pkgName)) {
                    //移除包
                    mItems.remove(item);
                    setAdapter();
                    break;
                }
            }
        }


    }

    private ApkListActivity.Model currentModel = ApkListActivity.Model.NORMAL;

    public void setModel(ApkListActivity.Model normal) {
        currentModel = normal;
        if (btnOneKeyBackup != null) {
            btnOneKeyBackup.setVisibility(currentModel == ApkListActivity.Model.BACKUP ? View.VISIBLE : View.GONE);
        }
        if (adapter != null) {
            adapter.setModel(currentModel);
        }
    }

    @OnClick({R.id.btnOneKeyBackup})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.btnOneKeyBackup:
                //点击开始备份apk
                ((BaseActivity) getActivity()).requestPermissions(new IPermissionManager.OnRequestPermissionListener() {
                    @Override
                    public void grantPermissions(boolean isAllGrant, String[] permissions) {
                        startBackup();
                    }

                    @Override
                    public void denyPermissions(boolean isAllDeny, String[] permissions) {

                    }
                }, Manifest.permission.WRITE_EXTERNAL_STORAGE);
                break;
        }
    }

    private void startBackup() {
        class UpdateProgress {
            int total;
            int current;
        }
        showLoading();
        Observable.create(new ObservableOnSubscribe<UpdateProgress>() {
            @Override
            public void subscribe(ObservableEmitter<UpdateProgress> e) throws Exception {
                Map<String, Boolean> checkedMap = adapter.getCheckedMap();
                Set<Map.Entry<String, Boolean>> entrySet = checkedMap.entrySet();
                UpdateProgress progress = new UpdateProgress();
                progress.total = checkedMap.size();
                progress.current = 0;
                for (Map.Entry<String, Boolean> entry : entrySet) {
                    progress.current++;
                    e.onNext(progress);
                    PackageInfo packageInfo = AppUtils.getPackageInfo(getContext(), entry.getKey());
                    if (packageInfo == null) {
                        continue;
                    }
                    backupApk(packageInfo);
                }
                e.onComplete();
            }
        }).compose(RxHelper.observableIO2Main()).subscribe(new Observer<UpdateProgress>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(UpdateProgress value) {

            }

            @Override
            public void onError(Throwable e) {
                dismissLoading();
                BaseActivity baseActivity = (BaseActivity) getActivity();
                baseActivity.showToast(e.getMessage());
            }

            @Override
            public void onComplete() {
                dismissLoading();
                BaseActivity baseActivity = (BaseActivity) getActivity();
                baseActivity.showToast("备份完成");
            }
        });

    }


    /**
     * 备份APK 使用rxjava 在子线程执行
     *
     * @param packageInfo
     */
    private boolean backupApk(PackageInfo packageInfo) {
        String source = AppUtils.getAppSourceDir(packageInfo);
        String key = AppUtils.getAppPackageName(packageInfo) + "_" + AppUtils.getAppVersionName(packageInfo);
        String appName = key + ".apk";
        //保存到目标位置/RxFrame/App目录下
        return FileManager.copyFileToFile(new File(source), new File(FileManager.getApkDir(), appName), true);
    }

    public enum Type {
        /**
         * 所有
         */
        ALL,
        /**
         * 用户安装的
         */
        USER,
        /**
         * 系统自带的
         */
        SYSTEM
    }


    private List<PackageInfo> mItems = new ArrayList<>();

    private void initData() {
        showLoading();
        uptCheckCount(0);
        Observable.create(new ObservableOnSubscribe<List<PackageInfo>>() {
            @Override
            public void subscribe(ObservableEmitter<List<PackageInfo>> e) throws Exception {
                List<PackageInfo> lists = mPackageManager
                        .getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
                //最终处理的结果
                List<PackageInfo> finalItems = new ArrayList<>();
                switch (getType()) {
                    case ALL:
                    default:
                        finalItems.addAll(lists);
                        break;
                    case USER:
                        for (PackageInfo pi : lists) {
                            if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                                finalItems.add(pi);
                            }
                        }
                        break;
                    case SYSTEM:
                        for (PackageInfo pi : lists) {
                            if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                                finalItems.add(pi);
                            }
                        }
                        break;
                }
                Collections.sort(finalItems, new DisplayNameComparator(mPackageManager));
                e.onNext(finalItems);
                e.onComplete();
            }
        }).compose(RxHelper.observableIO2Main()).subscribe(new Consumer<List<PackageInfo>>() {
            @Override
            public void accept(List<PackageInfo> items) throws Exception {
                //获取到结果数据
                mItems.clear();
                if (!ArrayUtils.isEmpty(items)) {
                    mItems.addAll(items);
                }
                setAdapter();
                dismissLoading();
            }
        });


    }

    ApkListAdapter adapter;

    private void setAdapter() {
        if (rcvContent == null) {
            return;
        }
        if (adapter == null) {
            rcvContent.setLayoutManager(new LinearLayoutManager(getContext()));
            adapter = new ApkListAdapter(mItems, getActivity().getPackageManager());
            adapter.setModel(currentModel);
            adapter.setOnCheckedCountChangeListener(new ApkListAdapter.OnCheckedCountChangeListener() {
                @Override
                public void onChange(int size) {
                    uptCheckCount(size);

                }
            });
            rcvContent.setAdapter(adapter);
        } else {
            adapter.notifyDataSetChanged();
        }
    }

    private void uptCheckCount(int size) {
        if (btnOneKeyBackup == null) {
            return;
        }
        if (size > 0) {
            btnOneKeyBackup.setText(getString(R.string.apk_one_key_backup, size + ""));
            btnOneKeyBackup.setEnabled(true);
        } else {
            btnOneKeyBackup.setText(getString(R.string.apk_one_key_backup_zero));
            btnOneKeyBackup.setEnabled(false);
        }

    }

    /**
     * 排序比较器
     */
    private static class DisplayNameComparator implements
            Comparator<PackageInfo> {
        public DisplayNameComparator(PackageManager pm) {
            mPM = pm;
            mCollator.setStrength(Collator.PRIMARY);
        }

        StorageStatsManager mStatsManager;
        UserHandle mHandler = null;

        public final int compare(PackageInfo a, PackageInfo b) {
            //高版本使用大小排序
            if (false && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                if (mStatsManager == null) {
                    mStatsManager = (StorageStatsManager) UIUtils.getContext().getSystemService(Context.STORAGE_STATS_SERVICE);
                    mHandler = UserHandle.getUserHandleForUid(-2);
                }
                try {
                    StorageStats stats = null;
                    stats = mStatsManager.queryStatsForPackage(StorageManager.UUID_DEFAULT, a.applicationInfo.packageName, mHandler);
                    long aTotal = stats.getAppBytes() + stats.getDataBytes() + stats.getCacheBytes();
                    stats = mStatsManager.queryStatsForPackage(StorageManager.UUID_DEFAULT, b.applicationInfo.packageName, mHandler);
                    long bTotal = stats.getAppBytes() + stats.getDataBytes() + stats.getCacheBytes();
//                    return (int) (aTotal - bTotal);//数值超过几个G后，会出现精度丢失
                    return mCollator.compare(toSizeString(bTotal), toSizeString(aTotal));
                } catch (PackageManager.NameNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (SecurityException e) { //这里说明没有权限，没有权限只能查询自身应用大小
                    e.printStackTrace();
                }
            }
            //按字符排序
            CharSequence sa = a.applicationInfo.loadLabel(mPM);
            if (sa == null)
                sa = a.packageName;
            CharSequence sb = b.applicationInfo.loadLabel(mPM);
            if (sb == null)
                sb = b.packageName;

            return mCollator.compare(sa.toString(), sb.toString());

        }

        private String toSizeString(long number) {
            String str = number + "";
            String newStr = (char) ('A' + str.length()) + str;
            return newStr;
        }

        private final Collator mCollator = Collator.getInstance();
        private PackageManager mPM;
    }

}
